package com.shijie.sjoj.service.core;

import com.shijie.sjoj.model.api.judge.JudgeService;
import com.shijie.sjoj.model.pojo.base.CodeType;
import com.shijie.sjoj.model.pojo.base.JudgedInfo;
import com.shijie.sjoj.model.pojo.entity.Judge;
import com.shijie.sjoj.model.utils.JsonFileUtils;
import com.shijie.sjoj.service.box.JudgeWorker;
import com.shijie.sjoj.service.box.JudgeWorkerCreator;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;

import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 判题机服务接口实现类
 *
 * @author ZSJ
 */
@Slf4j
@DubboService(timeout = 5000)
@RequiredArgsConstructor
public class JudgeServiceImpl implements JudgeService {

    /**
     * 判题机创建器
     */
    private final JudgeWorkerCreator judgeWorkerCreator;

    /**
     * 线程池
     */
    private final ExecutorService pools = Executors.newFixedThreadPool(10);

    @Override
    public JudgedInfo judge(Judge judge) {
        String code = judge.getCode();
        CodeType codeType = judge.getCodeType();
        Class<?>[] paramsType = judge.getParamsType();
        Path incomePath = judge.getIncomePath();
        Path outcomePath = judge.getOutcomePath();
        // 获取原型入参类型
        Class<?>[] argsType = Arrays.copyOf(paramsType, paramsType.length - 1);
        // 获取原型结果类型
        Class<?> outcomeType = paramsType[paramsType.length - 1];
        // 获取原型入参
        ArrayList<List<?>> args = JsonFileUtils.readJson4FilePath2(incomePath, new ArrayList<List<?>>(0));
        // 获取原型结果
        ArrayList<List<?>> outcome = JsonFileUtils.readJson4FilePath2(outcomePath, new ArrayList<List<?>>(0));
        log.info("""
                args:【{}】，
                outcome:【{}】，
                --- \033[1;32m开始判题机\033[0m
                """, args, outcome);
        // 获取对应的判题机
        JudgeWorker judgeWorker = judgeWorkerCreator.createJudgeWorker(codeType);
        // 解题
        JudgedInfo judgedInfo = judgeWorker.working(code, codeType, argsType, args, outcomeType, outcome);
        log.info("--- \033[1;32m结束判题机\033[0m");
        // 返回解题结果
        return judgedInfo;
    }


}
